home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / cpublit1 / part02 < prev   
Internet Message Format  |  1991-05-08  |  46KB

  1. Path: news.larc.nasa.gov!amiga-request
  2. From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v91i096: CpuBlit 1.0 - speeds up blitter on a 68020/30 Amiga, Part02/02
  4. Reply-To: ecarroll%maths.tcd.ie@pucc.PRINCETON.EDU
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga:v91i096@ab20.larc.nasa.gov>
  7. References: <comp.sources.amiga:v91i095@ab20.larc.nasa.gov>
  8. Date: 07 May 91 23:45:28 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga.misc
  12.  
  13. Submitted-by: ecarroll%maths.tcd.ie@pucc.PRINCETON.EDU
  14. Posting-number: Volume 91, Issue 096
  15. Archive-name: utilities/cpublit-1.0/part02
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 2 (of 2)."
  24. # Contents:  src/scroll.s
  25. # Wrapped by tadguy@ab20 on Tue May  7 19:45:25 1991
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'src/scroll.s' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'src/scroll.s'\"
  29. else
  30. echo shar: Extracting \"'src/scroll.s'\" \(42602 characters\)
  31. sed "s/^X//" >'src/scroll.s' <<'END_OF_FILE'
  32. X***************************************************************** :ts=8 *****
  33. X*
  34. X*    SCROLL.S
  35. X*
  36. X*    (C) Copyright Eddy Carroll, January 1991.
  37. X*
  38. X*    Replaces BltBitMap with a routine that uses the CPU (preferably
  39. X*    68030). This increases speed by a factor of about 2.8 on the A3000
  40. X*    when the cache is enabled or 2.0 when the cache is disabled.
  41. X*
  42. X*****************************************************************************
  43. X
  44. X    include "exec/types.i"
  45. X    include "exec/execbase.i"
  46. X    include "exec/nodes.i"
  47. X    include "graphics/gfx.i"
  48. X
  49. X    XDEF    _NewBltBitMap
  50. X    XDEF    _BltBitMapAddress
  51. X    XDEF    _OnlySingle
  52. X    XDEF    _UsageCount
  53. X    XDEF    _Broken
  54. X    XDEF    _BlitFunc
  55. X    XDEF    _MinTaskPri
  56. X    XDEF    _StartBlit
  57. X    XDEF    _ExitBlit
  58. X    XDEF    _ShareBlit
  59. X    XDEF    _Friend1
  60. X    XDEF    _Friend2
  61. X
  62. X    XREF    _SysBase
  63. X    XREF    _GfxBase
  64. X    XREF    _LVOWait
  65. X    XREF    _LVOWaitBlit
  66. X
  67. X    SECTION Scroll,CODE
  68. X
  69. X*****************************************************************************
  70. X*
  71. X*    NewBltBitMap()
  72. X*
  73. X*    Replacement BltBitMap which uses the 68030 instead of the blitter.
  74. X*    The following conditions must hold for the CPU routine to be used:
  75. X*
  76. X*        o    Bitmaps aligned on same longword bit offset
  77. X*        (i.e. XSrc % 32 == XDest % 32)
  78. X*
  79. X*        o    If source bitmap == destination bitmap, then YSrc != YDest
  80. X*
  81. X*        o    Blitter minterm = $Cx (i.e. straight copy)
  82. X*
  83. X*    If any of these conditions doesn't hold, then the original BltBitMap
  84. X*    is called instead.
  85. X*
  86. X*    Input:
  87. X*        D0 - X Source
  88. X*        D1 - Y Source
  89. X*        D2 - X Dest
  90. X*        D3 - Y Dest
  91. X*        D4 - X Size
  92. X*        D5 - Y Size
  93. X*        D6 - Minterm
  94. X*        D7 - Mask, indicating which planes are to be affected
  95. X*        A0 - Pointer to source bitmap structure
  96. X*        A1 - Pointer to destination bitmap structure
  97. X*        A2 - Pointer to temporary bitmap structure (not used)
  98. X*
  99. X*    Output:
  100. X*        D0 - Number of planes actually copied
  101. X*
  102. X*    The copy routine works as follows. Everything is done in longword
  103. X*    units. If the bitmap being copied fits horizontally into a single
  104. X*    longword, then the CopySingle() routine is used which copies a
  105. X*    single column of longwords, masked out as appropriate. Otherwise,
  106. X*    there are at least two longwords involved (the left and right edges
  107. X*    of the bitmap), with possibly some longwords inbetween as well.
  108. X*    CopyMultiple() is called to perform this copy; it uses two mask
  109. X*    values to identify which bits in the left and right longwords should
  110. X*    be copied. The longwords (if any) in between are copied verbatim.
  111. X*
  112. X*    Note that using longwords gives a big win on the A3000 since it can
  113. X*    access CHIP ram via the 32 bit bus. This relies on the data being
  114. X*    longword aligned of course. In the worst case (where a bitmap width
  115. X*    is not a multiple of 4), one out of every two rows will be longword
  116. X*    aligned, which is not too bad. In the more common case, every row
  117. X*    is longword aligned. For overscan users, it's best to have your
  118. X*    screen width a multiple of 32.
  119. X*
  120. X*****************************************************************************
  121. X
  122. XPreExit:
  123. X    move.w    (sp)+,d0        ; Restore original A0 register
  124. X    exg    d6,a0            ; Ignore following instruction
  125. X_ExitBlit:
  126. X    exg    d6,a0            ; Restore original A0 register
  127. XDoOldBlt:
  128. X    subq.l    #1,_UsageCount        ; Decrement number of callers in code
  129. Xoldblt2:
  130. X    move.l    (sp)+,d6        ; Restore original mask
  131. Xoldblit:
  132. X    jmp    dummy            ; Filled in with correct address later
  133. X
  134. X_BltBitMapAddress equ oldblit+2
  135. X
  136. Xdummy:    rts
  137. X
  138. X_NewBltBitMap:
  139. X    tst.w    d4            ; Check if width is zero
  140. X    beq.s    dummy            ; If it is, don't do anything
  141. X    cmp.l    a0,a1            ; Copying within the same bitmap?
  142. X    bne.s    nb1            ; If yes,
  143. X    cmp.w    d1,d3            ; and Y row is the same, then it's a
  144. X    beq.s    oldblit            ; sideways blit so use system routine
  145. X    bra.s    nb2            ; Else skip to next check
  146. Xnb1:
  147. X    tst.l    _OnlySingle        ; Should we handle different src/dest
  148. X    bne.s    oldblit            ; If not, use standard system blit
  149. Xnb2:
  150. X    move.l    d6,-(sp)        ; Save current minterm register
  151. X    and.b    #$f0,d6            ; Mask out low bits
  152. X    cmp.b    #$c0,d6            ; Is it standard COPY minterm?
  153. X    bne.s    oldblt2            ; If not, exit
  154. X    move.l    d0,d6            ; See if XSrc % 32 == XDest % 32
  155. X    eor.l    d2,d6            ; Low 5 bits should be zero if equal
  156. X    and.b    #$1f,d6            ;
  157. X    bne.s    oldblt2            ; If not, then have to do normal blit
  158. X    tst.l    _Broken            ; Are we accomodating broken s/w?
  159. X    bne.s    nb3            ; If so, skip checks
  160. X    tst.b    bm_Flags(a0)        ; Is source standard Amiga bitmap?
  161. X    bne.s    oldblt2            ; If not, use system blit routine
  162. X    tst.w    bm_Pad(a0)        ; 
  163. X    bne.s    oldblt2            ;
  164. X    tst.b    bm_Flags(a1)        ; How about destination?
  165. X    bne.s    oldblt2            ; If it isn't, use system blit
  166. X    tst.w    bm_Pad(a1)        ; 
  167. X    bne.s    oldblt2            ;
  168. Xnb3:
  169. X    addq.l    #1,_UsageCount        ; Increment usage count
  170. X    exg    d6,a0            ; Save current A0
  171. X    move.l    _BlitFunc,a0        ; Get pointer to appropriate test func
  172. X    jmp    (a0)            ; And branch to it
  173. X;
  174. X;    Checks the usage count for the blitter code, to see if anyone else
  175. X;    is currently executing it. If so, use the blitter instead (hence
  176. X;    CPU does one blit while blitter does the other blit; multiprocessing!)
  177. X;
  178. X_ShareBlit:
  179. X    exg    d6,a0            ; Restore old A0
  180. X    move.l    _UsageCount,d6        ; Check if someone already in code
  181. X    bne    DoOldBlt        ; If there is, use blitter instead
  182. X    bra.s    sblit2            ; Else skip to use CPU
  183. X;
  184. X;    Checks to see if there is more than one task ready to run. If so,
  185. X;    use the blitter, else use the CPU. Note that for the most common case
  186. X;    of scrolling (in a CLI/console window), the task outputting the text
  187. X;    that causes the scroll will be "Ready to Run" since it is pre-empted
  188. X;    by the console device before it has a chance to go into a Wait
  189. X;    condition.
  190. X;
  191. X;    If there is more than one task ready to run, but the second task
  192. X;    in the queue has priority < MinTaskPri, then we can use the CPU
  193. X;    anyway (since the second task is a background task that can be
  194. X;    ignored).
  195. X;
  196. X_Friend2:
  197. X    move.l    _SysBase,a0        ; Get pointer to ExecBase
  198. X    lea.l    TaskReady(a0),a0    ; Get ptr to TaskReady list
  199. X    cmp.l    8(a0),a0        ; Empty list?
  200. X    beq.s    _StartBlit        ; If yes, do blit
  201. X    move.w    d0,-(sp)        ; Grab a register temporarily
  202. X    move.l    (a0),a0            ; Get pointer to first waiting task
  203. X    move.l    (a0),a0            ; Get pointer to second task
  204. X    move.b    LN_PRI(a0),d0        ; Get its priority (if it exists)
  205. X    move.l    (a0),a0            ; And final link ptr (NULL if at end)
  206. X    exg    d6,a0            ; Restore previous A0
  207. X    tst.l    d6            ; More than 1 task?
  208. X    beq.s    F2Okay            ; If no, we can use the blitter anyway
  209. X    cmp.b    _MinTaskPri,d0        ; Should we make way for waiting task?
  210. X    bge    PreExit            ; If so, use blitter instead
  211. XF2Okay:
  212. X    move.w    (sp)+,d0        ; Else restore D0
  213. X    bra.s    sblit2            ; And skip to start blit
  214. X;
  215. X;    Checks to see if there are _any_ other tasks ready to run. If there
  216. X;    are and their task priority is >= MinTaskPri, then uses system blit
  217. X;    instead of CPU.
  218. X;
  219. X_Friend1:
  220. X    move.l    _SysBase,a0        ; Get pointer to ExecBase
  221. X    lea.l    TaskReady(a0),a0    ; Get ptr to TaskReady list, head node
  222. X    cmp.l    8(a0),a0        ; Empty list?
  223. X    beq.s    _StartBlit        ; If yes, we can safely blit
  224. X    move.l    (a0),a0            ; Get pointer to first task
  225. X    move.w    LN_TYPE(a0),a0        ; Read ln_Type and ln_Pri
  226. X    exg    d6,a0            ; Restore a0
  227. X    cmp.b    _MinTaskPri,d6        ; Should we ignore this task?
  228. X    bge    DoOldBlt        ; If not, then use blitter instead
  229. X    bra.s    sblit2            ; Else skip to use CPU
  230. X
  231. X;----------------------------------------------------------------------------
  232. X;    Where the action starts. Initialises everything and then performs
  233. X;    the blits using the CPU. At this stage, all registers are exactly
  234. X;    as they were on entry to BltBitMap, except for D6 and A0, and these
  235. X;    two are restored to the correct values immediately on entry.
  236. X;----------------------------------------------------------------------------
  237. X_StartBlit:
  238. X    exg    d6,a0            ; Restore A0
  239. Xsblit2:                    ; Alternative entry point
  240. X;
  241. X;    Now we need to determine the masks to be used for clipping, along
  242. X;    with the start address in memory of the section of the bit and
  243. X;    the modulo of each bitplane (the amount added onto the end of each
  244. X;    copied row address to get to the start of the next one). Then loop
  245. X;    over all the selected bitplanes, copying those requested.
  246. X;
  247. X    movem.l    d1-d5/d7/a0-a6,-(sp)    ; Save rest of the registers
  248. X;
  249. X;    Next, we need to make sure that the blitter is free. This is because
  250. X;    some other blitter operation that operates on the bitmaps we've been
  251. X;    passed may have started but not yet finished. Operations that
  252. X;    depend on the blitter are guaranteed to occur in the right order
  253. X;    (since the blitter can't multitask with itself) but when we start
  254. X;    doing some of them with the CPU, we need to be a bit more careful.
  255. X;
  256. X;    Note: Since we are now "in" graphics.library, a6 holds GfxBase.
  257. X;          WaitBlit() is documented as preserving all registers.
  258. X;
  259. X    jsr    _LVOWaitBlit(a6)    ; Wait for blitter to become free
  260. X    ext.l    d0            ; Convert all parameters to long
  261. X    ext.l    d1            ;
  262. X    ext.l    d2            ;
  263. X    ext.l    d3            ;
  264. X    ext.l    d4            ;
  265. X    ext.l    d5            ;
  266. X
  267. X    cmp    d1,d3            ; See if we are scrolling up or down
  268. X    bhi    bltdown            ;
  269. X;
  270. X;    Since YDest < YSrc, we are copying the bitmap upwards in memory
  271. X;    therefore start at the beginning and work down. (This is only
  272. X;    important if the source and destination bitmaps are the same, but
  273. X;    it doesn't do any harm to check when they are different also.)
  274. X;
  275. Xbltup:
  276. X    move.w    bm_BytesPerRow(a0),d6    ; Get width of source bitmap
  277. X    ext.l    d6            ; Extend to full integer
  278. X    move.l    d6,a2            ; Initialise modulo for source bitmap
  279. X    muls    d6,d1            ; Calculate row offset
  280. X    move.l    d0,d6            ; Get XSrc
  281. X    lsr.l    #3,d6            ; Get #bytes offset of XSrc
  282. X    and.b    #$fc,d6            ; Adjust to longword boundary
  283. X    add.l    d6,d1            ; Add on x offset to get bitmap offset
  284. X    move.l    d1,a4            ; Now A4 = offset into source bitmap
  285. X;
  286. X;    Repeat for dest bitmap
  287. X;
  288. X    move.w    bm_BytesPerRow(a1),d6    ; Get width of dest bitmap
  289. X    ext.l    d6            ; Extend to full integer
  290. X    move.l    d6,a3            ; Initialise modulo for dest bitmap
  291. X    muls    d6,d3            ; Calculate row offset
  292. X    move.l    d2,d6            ; Get XDest
  293. X    lsr.l    #3,d6            ; (Converted to longword aligned
  294. X    and.b    #$fc,d6            ; byteoffset)
  295. X    add.l    d6,d3            ; Add on xoffset to get bitmap offset
  296. X    move.l    d3,a5            ; Now A5 = offset into dest bitmap
  297. X    bra.s    contblit        ; Skip to rest of blitcopy
  298. X;
  299. X;    If we get here, YDest > YSrc, so we are copying the bitmap downwards
  300. X;    which means we need to start from the end and work back. We also
  301. X;    need to initialise the modulo to -BytesPerRow instead of BytesPerRow.
  302. X;
  303. Xbltdown:
  304. X    add.l    d5,d1            ; Add YSize+YSrc to get last row addr
  305. X    subq.l    #1,d1            ; Adjust (so we don't have last_row+1)
  306. X    move.w    bm_BytesPerRow(a0),d6    ; Get width of source bitmap
  307. X    ext.l    d6            ; Extend to full longword
  308. X    muls    d6,d1            ; Calculate row offset
  309. X    neg.l    d6            ; Negate mod. since copying backwards
  310. X    move.l    d6,a2            ; Initialise modulo for source bitmap
  311. X    move.l    d0,d6            ; Get XSrc
  312. X    lsr.l    #3,d6            ; Get #bytes offset of XSrc
  313. X    and.b    #$fc,d6            ; Adjust to longword boundary
  314. X    add.l    d6,d1            ; Add on x offset to get bitmap offset
  315. X    move.l    d1,a4            ; Now A4 = offset into source bitmap
  316. X;
  317. X;    Do same calculations for dest bitmap
  318. X;
  319. X    add.l    d5,d3            ; Add YSize+YSrc to get last row addr
  320. X    subq.l    #1,d3            ; Adjust (so we don't have last_row+1)
  321. X    move.w    bm_BytesPerRow(a1),d6    ; Get width of dest bitmap
  322. X    ext.l    d6            ; Extend to full longword
  323. X    muls    d6,d3            ; Calculate row offset
  324. X    neg.l    d6            ; Negate, since copying backwards
  325. X    move.l    d6,a3            ; Initialise modulo for dest bitmap
  326. X    move.l    d2,d6            ; Get XDest
  327. X    lsr.l    #3,d6            ; (Converted to longword aligned
  328. X    and.b    #$fc,d6            ; byteoffset)
  329. X    add.l    d6,d3            ; Add on xoffset to get bitmap offset
  330. X    move.l    d3,a5            ; Now A5 = offset into dest bitmap
  331. X;
  332. X;    Now calculate the mask values
  333. X;
  334. Xcontblit:
  335. X    and.w    #$1f,d0            ; Calculate XSrc longword bit offset
  336. X    add.l    d0,d4            ; Calculate width of bitmap
  337. X    move.l    d4,d1            ; Calculate longword bit offset
  338. X    and.w    #$1f,d1            ;
  339. X    lsr.l    #5,d4            ; Calc # of longwords needed for copy
  340. X    add.l    d1,d1            ; Scale XWidth bits to longword index
  341. X    add.l    d1,d1            ; into the bitmask array
  342. X    bne.s    contb1            ; If zero,
  343. X    subq.l    #1,d4            ; Decrement longword count
  344. Xcontb1:
  345. X    lea    RightMask(PC),a6    ; Get address of right mask table
  346. X    move.l    0(a6,d1.w),d2        ; Get right bitmask
  347. X    add.l    d0,d0            ; Scale XSrc bits to longword index
  348. X    add.l    d0,d0            ; And again
  349. Xcontb2:
  350. X    lea    LeftMask(PC),a6        ; Get address of left mask table
  351. X    move.l    0(a6,d0.w),d1        ; Get left bitmask
  352. X;
  353. X;    Calculate minimum number of bitplanes to copy
  354. X;
  355. X    moveq.l    #0,d6            ; Zero out high bits of D6
  356. X    move.b    bm_Depth(a0),d6        ; Get depth of source bitmap
  357. X    cmp.b    bm_Depth(a1),d6        ; If greater than that of dest bitmap
  358. X    blo.s    contb3            ;
  359. X    move.b    bm_Depth(a1),d6        ; Use dest bitmap depth instead
  360. Xcontb3:
  361. X    subq.l    #1,d6            ; Adjust depth to 0-based, not 1-based
  362. X    move.l    d4,d0            ; Copy longword count
  363. X    addq.l    #1,d0            ; Adjust positively
  364. X    add.l    d0,d0            ; Convert longword count to byte count
  365. X    add.l    d0,d0            ;
  366. X    sub.l    d0,a2            ; Calculate correct modulo for source
  367. X    sub.l    d0,a3            ; Calculate correct modulo for dest.
  368. X    exg    a2,a4            ; Setup A2/A3 = bitmap offsets
  369. X    exg    a3,a5            ;  and  A4/A5 = bitmap modulos
  370. X
  371. X    subq.l    #1,d4            ; Adjust longword count to zero-based
  372. X    move.l    d4,d3            ; Move to right reg for Copy routine
  373. X    move.l    d5,d0            ; Copy YSize to right place also
  374. X    lea.l    bm_Planes(a0),a0    ; Get pointer to source bitplane array
  375. X    lea.l    bm_Planes(a1),a1    ; Get pointer to dest bitplane array
  376. X    move.l    a0,d4            ; Stash bitplane pointers here
  377. X    move.l    a1,d5            ;
  378. X    move.l    20(sp),d7        ; Read plane mask value from stack
  379. X;
  380. X;    Now build a list of bitmaps to be copied on the stack. To this end,
  381. X;    we reserve 8 * 8 = 64 bytes of stack for source/destination bitmap
  382. X;    pointers.
  383. X;
  384. X    lea    -64(sp),sp        ; Reserve space for bitmap ptrs
  385. X    move.l    sp,a6            ; And point to it using A6
  386. X;
  387. X;    Loop through bitmaps building bitmap list for bitmaps specified in
  388. X;    the copy mask. Bitplanes which have source and/or destination bitmaps
  389. X;    set to NULL or -1 get handled immediately (new for WB 2.0). All others
  390. X;    get stored on the stack.
  391. X;
  392. X    move.w    d7,-(sp)        ; Save plane mask as temporary value
  393. X    moveq.l    #0,d7            ; Clear bitmap plane count
  394. Xcmultlp:
  395. X    lsr.w    (sp)            ; See if need to copy this bitplane
  396. X    bcc.s    cmultx            ; If not, skip over code
  397. X    addq    #1,d7            ; Increment number of bitmaps copied
  398. X    move.l    d4,a0            ; Get pointer to source bitplane ptr
  399. X    move.l    d5,a1            ; And destination bitplane ptr
  400. X    move.l    (a0),d4            ; Read pointers to bitplanes
  401. X    move.l    (a1),d5            ;
  402. X    not.l    d5            ; Check if dest is -1
  403. X    beq    skipfill        ; If so, don't copy anything
  404. X    not.l    d5            ; Check if dest is zero
  405. X    beq    skipfill        ; If so, don't copy anything
  406. X    not.l    d4            ; Check if source is -1
  407. X    beq    fillones        ; If so, fill dest with 1's
  408. X    not.l    d4            ; Check if source is 0
  409. X    beq    fillzeros        ; If so, fill dest with 0's
  410. X    exg    d4,a0            ; Put registers back in right place
  411. X    exg    d5,a1            ;
  412. X    add.l    a2,a0            ; Add in correct offset for src ptr
  413. X    add.l    a3,a1            ; Add in correct offset for dest ptr
  414. X    move.l    a0,(a6)+        ; Store bitmap pointers on the stack
  415. X    move.l    a1,(a6)+        ;     
  416. Xcmultx:
  417. X    addq.l    #4,d4            ; Bump bitplane pointers
  418. X    addq.l    #4,d5            ;
  419. X    dbf    d6,cmultlp        ; Repeat for remaining bitplanes
  420. X    addq.l    #2,sp            ; Pop plane mask from stack
  421. X;
  422. X;    Now copy all the bitmaps we accumulated on the stack. There will be
  423. X;    between 1 and 8 of them. We copy them in groups of 1 to 4, so two
  424. X;    operations may be required.
  425. X;
  426. X;    A quick recap on what the various registers contain:
  427. X;
  428. X;        D0 - Number of rows to copy
  429. X;        D1 - Mask for left edge of bitmap
  430. X;        D2 - Mask for right edge of bitmap
  431. X;        D3 - Number of longwords _between_ left edge and right edge
  432. X;        D7 - Total number of bitplanes copied (including 0 & -1 ptrs)
  433. X;        A4 - Modulo of source bitplanes
  434. X;        A5 - Modulo of dest bitplanes
  435. X;        A6 - Points to end of source/dest bitplane pointers
  436. X;        SP - Points to start of source/dest bitplane pointers
  437. X;
  438. X    sub.l    sp,a6            ; Calculate how many bitplanes to copy
  439. X    move.l    a6,d6            ; Equals half # of source/dest pairs
  440. X    lsr.l    #1,d6            ; (giving a range of 0-28)
  441. X    subq    #4,d6            ; Adjust to zero based
  442. X    bpl.s    cmultx2            ; If negative, no bitplanes to copy
  443. X    lea    64(sp),sp        ; so pop bitplane pointers from stack
  444. X    bra    doneblt            ; and exit without doing any work
  445. Xcmultx2:
  446. X    cmpi.w    #12,d6            ; More than 4 bitplanes to copy?
  447. X    bhi.s    cmult_db        ; If so, skip to do in two goes
  448. X    move.l    d3,d3            ; Does bitmap fits in one longword?
  449. X    bpl.s    cmult_mm        ; If not, skip to multiple longwords
  450. X;
  451. X;    We have between 1 and 4 bitplanes to copy, each a single
  452. X;    longword wide.
  453. X;
  454. X    and.l    d2,d1            ; Create composite mask
  455. X    addq    #8,d6            ; Adjust to index CopySingle() entries
  456. X    addq    #8,d6            ; and then fall through.
  457. X;
  458. X;    We have between 1 and 4 bitplanes to copy, each at least two
  459. X;    longwords wide.
  460. X;
  461. Xcmult_mm:
  462. X    move.l    FuncTab(pc,d6),a6    ; Else call appropriate routine
  463. X    jsr    (a6)            ;
  464. X    lea    64(sp),sp        ; Pop everything off the stack
  465. X    bra    doneblt            ; And skip to end of blit
  466. X
  467. Xcmult_db:
  468. X    move.l    d3,d3            ; Does bitplane fit in one longword?
  469. X    bpl.s    cmult_dbm        ; If not, skip to multiple copy
  470. X;
  471. X;    We have between 5 and 8 bitplanes to copy, each just one
  472. X;    longword wide. Note that when we exit, we branch into the code to
  473. X;    copy the remaining bitmaps, but with the function index pointing
  474. X;    into the CopySingle() entries rather than CopyMultiple()
  475. X;
  476. X    and.l    d2,d1            ; Create composite mask
  477. X    bsr    Copy4Single        ; Copy first four bitplanes
  478. X    bra.s    cmult_dbm2        ; Skip to exit with correct fn index
  479. X;
  480. X;    We have between 5 and 8 bitplanes to copy, each at least two
  481. X;    longwords wide.
  482. X;
  483. Xcmult_dbm:
  484. X    bsr    Copy4Multiple        ; Copy first four bitmaps in one gulp
  485. X    subi.w    #16,d6            ; Adjust bitmap count
  486. Xcmult_dbm2:
  487. X    lea    32(sp),sp        ; Pop first four bitmaps off stack
  488. X    move.l    FuncTab(pc,d6),a6    ; Copy remaining bitmaps
  489. X    jsr    (a6)            ;
  490. X    lea    32(sp),sp        ; Pop remaining bitmaps
  491. X    bra    doneblt            ; And skip to end of blit
  492. X
  493. X;
  494. X;    Index to table of functions for copying from 1 to 4 multiple and
  495. X;    single longword bitmaps.
  496. X;
  497. XFuncTab:
  498. X    dc.l    Copy1Multiple,Copy2Multiple,Copy3Multiple,Copy4Multiple
  499. X    dc.l    Copy1Single,Copy2Single,Copy3Single,Copy4Single
  500. X
  501. X;
  502. X;    Skip past current bitplane without doing anything to bitplane data
  503. X;    (used when destination bitmap ptr is 0 or -1).
  504. X;
  505. Xskipfill:
  506. X    exg    d4,a0            ; Restore original pointers
  507. X    exg    d5,a1            ;
  508. X    bra    cmultx            ; Skip back to do next bitplane
  509. X;
  510. X;    Fill bitplane with one's (source bitplane pointer is -1)
  511. X;
  512. Xfillones:
  513. X    exg    d4,a0            ; Restore register order
  514. X    exg    d5,a1            ;
  515. X    add.l    a3,a1            ; Add in correct offset into bitplane
  516. X    bsr    Fill_1s            ; Fill the bitplane
  517. X    bra    cmultx            ; Skip back to do next bitplane
  518. X;
  519. X;    Fill bitplane with zero's (source bitplane pointer is NULL)
  520. X;
  521. Xfillzeros:
  522. X    exg    d4,a0            ; Restore register order
  523. X    exg    d5,a1            ;
  524. X    add.l    a3,a1            ; Add in correct offset into bitplane
  525. X    bsr    Fill_0s            ; Fill the bitplane
  526. X    bra    cmultx            ; Skip back to do next bitplane
  527. X;
  528. X;    That's it -- we're done! Now just pop remaining values off the stack
  529. X;    and return to the caller with d0 = number of bitplanes copied.
  530. X;
  531. Xdoneblt:
  532. X    move.l    d7,d0            ; Set return value = #bitplanes copied
  533. X    subq.l    #1,_UsageCount        ; Decrement number of callers in code
  534. X    movem.l    (sp)+,d1-d5/d7/a0-a6    ; Restore registers
  535. X    move.l    (sp)+,d6        ; And this one too
  536. X    rts                ; Return to caller
  537. X
  538. X*****************************************************************************
  539. X*
  540. X*    CopyMultiple()
  541. X*
  542. X*    The following routines copy from 1 to 4 bitplanes which span more
  543. X*    than one longword boundary horizontally (i.e. the start and finish
  544. X*    bitplanes are in different longwords).
  545. X*
  546. X*    The routines are constructed mainly out of macros, to keep the source
  547. X*    code down to size (and also more manageable). All routines take the
  548. X*    following parameters:
  549. X*
  550. X*    Input:
  551. X*        D0 - Number of rows to copy
  552. X*        D1 - Mask for left edge of source    (000xxx)
  553. X*        D2 - Mask for right edge of source    (xxx000)
  554. X*        D3 - Number of longwords to copy
  555. X*            A4 - Modulo of source (positive or negative)
  556. X*            A5 - Modulo of destination (positive or negative)
  557. X*
  558. X*    In addition, pointers to the source/destination bitplanes are pushed
  559. X*    onto the stack, such that 4(SP) = src bp1, 8(SP) = dest bp1,
  560. X*    12(SP) = src bp2, 16(SP) = dest bp2 etc.
  561. X*
  562. X*    Output:
  563. X*        None
  564. X*
  565. X*****************************************************************************
  566. X
  567. X*****************************************************************************
  568. X*
  569. X*    Macros used by the copy routines
  570. X*
  571. X*****************************************************************************
  572. X
  573. X;-----------------------------------------------------------------------------
  574. X;    Init_Mult Label
  575. X;
  576. X;    This macro is the standard entry to each CopyMultiple() routine. It
  577. X;    checks to see whether the bitplane being copied contains at least
  578. X;    one full longword. If not, it branches to a separate routine
  579. X;    (loop?edges) which is smaller; doing this at the start saves having
  580. X;    to check for zero longwords each time through the main loop.
  581. X;    Label is the name of the routine to perform the separate copy.
  582. X;-----------------------------------------------------------------------------
  583. X
  584. XInit_Mult macro
  585. X    subq.l    #1,d0            ; Convert row count to zero-based
  586. X    move.l    d1,d4            ; Copy left source mask
  587. X    not.l    d4            ; And change it into destination mask
  588. X    move.l    d2,d5            ; Copy right source mask
  589. X    not.l    d5            ; Change into destination mask
  590. X    subq.l    #1,d3            ; Adjust longword count to zero based
  591. X    bmi    \1            ; If none to copy use seperate routine
  592. X    endm
  593. X
  594. X;-----------------------------------------------------------------------------
  595. X;    Left_Mult   src,dest
  596. X;
  597. X;    Copies the left hand side of the bitplane from register src to the
  598. X;    bitplane pointed to by dest, using the masks in d1/d4
  599. X;-----------------------------------------------------------------------------
  600. X
  601. XLeft_Mult macro
  602. X    move.l    (\1)+,d6        ; Read leftmost longword of source
  603. X    and.l    d1,d6            ; Mask out bits not to be copied
  604. X    move.l    (\2),d7            ; Read leftmost longword of dest
  605. X    and.l    d4,d7            ; Mask out bits to remain the same
  606. X    or.l    d6,d7            ; Merge source and dest columns
  607. X    move.l    d7,(\2)+        ; Output first word of bitplane again
  608. X    endm
  609. X
  610. X;-----------------------------------------------------------------------------
  611. X;    Copy_Mult src,dest
  612. X;
  613. X;    Copies all the full longwords between the left and right extremities
  614. X;    of the bitplane row from src to dest. Note that for 68010 upwards, it
  615. X;    is faster to copy using MOVE.L/DBF than to play tricks with MOVEM;
  616. X;    since this program will only be of use to systems with fast CPU's
  617. X;    anyway, this is the route we take.
  618. X;-----------------------------------------------------------------------------
  619. X
  620. XCopy_Mult macro
  621. X    move.l    d3,d6            ; Copy longword count into scratch reg
  622. Xloop_m\@:
  623. X    move.l    (\1)+,(\2)+        ; Copy longwords
  624. X    dbf    d6,loop_m\@        ;
  625. X    endm
  626. X
  627. X;-----------------------------------------------------------------------------
  628. X;    Right_Mult   src,dest
  629. X;
  630. X;    Copies the right hand side of the bitplane from register src to the
  631. X;    bitplane pointed to by dest, using the masks in d2/d5
  632. X;-----------------------------------------------------------------------------
  633. X
  634. XRight_Mult macro
  635. X    move.l    (\1)+,d6        ; Read rightmost longword of source
  636. X    and.l    d2,d6            ; Mask out bits not being copied
  637. X    move.l    (\2),d7            ; Read rightmost longword of dest
  638. X    and.l    d5,d7            ; Mask out bits to remain the same
  639. X    or.l    d6,d7            ; Merge source and dest columns
  640. X    move.l    d7,(\2)+        ; Output right longword again
  641. X    endm
  642. X
  643. X;-----------------------------------------------------------------------------
  644. X;    Advance src,dest
  645. X;
  646. X;    This macro advances the source and destination pointers to point to
  647. X;    the next row in the bitplane.
  648. X;-----------------------------------------------------------------------------
  649. X
  650. XAdvance macro
  651. X    add.l    a4,\1            ; Increment source pointer
  652. X    add.l    a5,\2            ; Increment dest pointer
  653. X    endm
  654. X
  655. X;-----------------------------------------------------------------------------
  656. X;    Copy_Quick src,dest
  657. X;
  658. X;    This macro copies the left and right edges in one go, when there
  659. X;    are no complete longwords in between. It's quicker than having to
  660. X;    check for zero longwords each time through the main loop. The masks
  661. X;    used are d1/d4 for the left edge of the bitplane, d2/d5 for the
  662. X;    right edge.
  663. X;-----------------------------------------------------------------------------
  664. X
  665. XCopy_Quick macro
  666. X    move.l    (\1)+,d6        ; Read leftmost longword of source
  667. X    and.l    d1,d6            ; Mask out bits not to be copied
  668. X    move.l    (\2),d7            ; Read leftmost longword of dest
  669. X    and.l    d4,d7            ; Mask out bits to remain the same
  670. X    or.l    d6,d7            ; Merge source and dest columns
  671. X    move.l    d7,(\2)+        ; Output first word of bitplane again
  672. X;
  673. X;    Now tidy up right hand edge of bitplane
  674. X;
  675. X    move.l    (\1)+,d6        ; Read rightmost longword of source
  676. X    and.l    d2,d6            ; Mask out bits not being copied
  677. X    move.l    (\2),d7            ; Read rightmost longword of dest
  678. X    and.l    d5,d7            ; Mask out bits to remain the same
  679. X    or.l    d6,d7            ; Merge source and dest columns
  680. X    move.l    d7,(\2)+        ; Output right longword again
  681. X    endm
  682. X
  683. X*****************************************************************************
  684. X*
  685. X*    The actual copy routines, Copy1Multiple() ... Copy4Multiple()
  686. X*
  687. X*****************************************************************************
  688. X
  689. X;-----------------------------------------------------------------------------
  690. X;
  691. X;    Copies a single bitplane
  692. X;
  693. X;-----------------------------------------------------------------------------
  694. X
  695. XCopy1Multiple:
  696. X    movem.l    a0-a1/a6/d0-d7,-(sp)    ; Save registers
  697. X    lea.l        48(sp),a6    ; Get pointer to stack
  698. X    move.l        (a6)+,a0    ; Read bitplane pointers from stack
  699. X    move.l        (a6)+,a1    ; Read bitplane pointers from stack
  700. X    Init_Mult    Copy1Quick    ; Setup registers
  701. Xc1m_loop:
  702. X    Left_Mult    a0,a1        ; Copy left edge of bitplane
  703. X    Copy_Mult    a0,a1        ; Copy middle of bitplane
  704. X    Right_Mult    a0,a1        ; Copy right edge of bitplane
  705. X    Advance        a0,a1        ; Increment bitplane ptrs
  706. X    dbf        d0,c1m_loop    ; Repeat for remaining rows
  707. X    movem.l    (sp)+,a0-a1/a6/d0-d7    ; Restore registers
  708. X    rts                ; Return to caller
  709. X;
  710. X;    Handle inner longword count of zero
  711. X;
  712. XCopy1Quick:
  713. X    Copy_Quick    a0,a1        ; Copy left/right edge of bitplane
  714. X    Advance        a0,a1        ; Increment bitplane ptrs
  715. X    dbra        d0,Copy1Quick    ; Repeat for all rows
  716. X    movem.l    (sp)+,a0-a1/a6/d0-d7    ; Restore registers
  717. X    rts                ; Return to caller
  718. X
  719. X;-----------------------------------------------------------------------------
  720. X;
  721. X;    Copies 2 bitplanes simultaneously
  722. X;
  723. X;-----------------------------------------------------------------------------
  724. X
  725. XCopy2Multiple:
  726. X    movem.l    a0-a3/a6/d0-d7,-(sp)    ; Save registers
  727. X    lea.l        56(sp),a6    ; Get pointer to bitplanes
  728. X    movem.l        (a6),a0-a3    ; Load bitplane ptrs off stack
  729. X    Init_Mult    Copy2Quick    ; Setup registers
  730. Xc2m_loop:
  731. X    Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  732. X    Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  733. X    Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  734. X    Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  735. X    Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  736. X    Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  737. X    Advance        a0,a1        ; Increment bitplane 1 ptrs
  738. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  739. X    dbf        d0,c2m_loop    ; Repeat for remaining rows
  740. X    movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  741. X    rts                ; Return to caller
  742. X;
  743. X;    Handle inner longword count of zero
  744. X;
  745. XCopy2Quick:
  746. X    Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 1
  747. X    Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  748. X    Advance        a0,a1        ; Increment bitplane 1 ptrs
  749. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  750. X    dbra        d0,Copy2Quick    ; Repeat for all rows
  751. X    movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  752. X    rts                ; Return to caller
  753. X
  754. X;-----------------------------------------------------------------------------
  755. X;
  756. X;    Copies 3 bitplanes simultaneously
  757. X;
  758. X;-----------------------------------------------------------------------------
  759. X
  760. XCopy3Multiple:
  761. X    movem.l    a0-a3/a6/d0-d7,-(sp)    ; Save registers
  762. X    lea.l        56(sp),a6    ; Get pointer to bitplanes
  763. X    movem.l        (a6)+,a0-a3    ; Load bitplane ptrs 1 & 2 off stack
  764. X    Init_Mult    Copy3Quick    ; Setup registers
  765. Xc3m_loop:
  766. X    Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  767. X    Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  768. X    Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  769. X    Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  770. X    Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  771. X    Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  772. X    Advance        a0,a1        ; Increment bitplane 1 ptrs
  773. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  774. X    move.l        a3,-(sp)    ; Save bitplane 2 ptrs
  775. X    move.l        a2,-(sp)    ;
  776. X    move.l        (a6)+,a2    ; Load bitplane 3 ptrs
  777. X    move.l        (a6),a3        ; 
  778. X    Left_Mult    a2,a3        ; Copy left edge of bitplane 3
  779. X    Copy_Mult    a2,a3        ; Copy middle of bitplane 3
  780. X    Right_Mult    a2,a3        ; Copy right edge of bitplane 3
  781. X    Advance        a2,a3        ; Increment bitplane 3 ptrs
  782. X    move.l        a3,(a6)        ; Save bitplane 3 ptrs
  783. X    move.l        a2,-(a6)    ;
  784. X    move.l        (sp)+,a2    ; Restore bitplane 2 ptrs
  785. X    move.l        (sp)+,a3    ;
  786. X    dbf        d0,c3m_loop    ; Repeat for remaining rows
  787. X    movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  788. X    rts                ; Return to caller
  789. X;
  790. X;    Handle inner longword count of zero
  791. X;
  792. XCopy3Quick:
  793. X    Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 1
  794. X    Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  795. X    Advance        a0,a1        ; Increment bitplane 1 ptrs
  796. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  797. X    move.l        a3,-(sp)    ; Save bitplane 2 ptrs
  798. X    move.l        a2,-(sp)    ;
  799. X    move.l        (a6)+,a2    ; Load bitplane 3 ptrs
  800. X    move.l        (a6),a3        ; 
  801. X    Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  802. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  803. X    move.l        a3,(a6)        ; Save bitplane 3 ptrs
  804. X    move.l        a2,-(a6)    ;
  805. X    move.l        (sp)+,a2    ; Restore bitplane 2 ptrs
  806. X    move.l        (sp)+,a3    ;
  807. X    dbra        d0,Copy3Quick    ; Repeat for all rows
  808. X    movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  809. X    rts                ; Return to caller
  810. X
  811. X;-----------------------------------------------------------------------------
  812. X;
  813. X;    Copies 4 bitplanes simultaneously
  814. X;
  815. X;-----------------------------------------------------------------------------
  816. X
  817. XCopy4Multiple:
  818. X    movem.l    a0-a3/a6/d0-d7,-(sp)    ; Save registers
  819. X    lea.l        56(sp),a6    ; Get pointer to bitplanes
  820. X    movem.l        (a6)+,a0-a3    ; Load bitplane ptrs 1 & 2 off stack
  821. X    Init_Mult    Copy4Quick    ; Setup registers
  822. Xc4m_loop:
  823. X    Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  824. X    Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  825. X    Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  826. X    Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  827. X    Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  828. X    Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  829. X    Advance        a0,a1        ; Increment bitplane 1 ptrs
  830. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  831. X    movem.l        a0-a3,-(sp)    ; Save bitplane 2 ptrs
  832. X    movem.l        (a6),a0-a3    ; Load bitplane 3 ptrs
  833. X    Left_Mult    a0,a1        ; Copy left edge of bitplane 1
  834. X    Left_Mult    a2,a3        ; Copy left edge of bitplane 2
  835. X    Copy_Mult    a0,a1        ; Copy middle of bitplane 1
  836. X    Copy_Mult    a2,a3        ; Copy middle of bitplane 2
  837. X    Right_Mult    a0,a1        ; Copy right edge of bitplane 1
  838. X    Right_Mult    a2,a3        ; Copy right edge of bitplane 2
  839. X    Advance        a0,a1        ; Increment bitplane 1 ptrs
  840. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  841. X    movem.l        a0-a3,(a6)    ; Save bitplane 3 ptrs
  842. X    movem.l        (sp)+,a0-a3    ; Restore bitplane 2 ptrs
  843. X    dbf        d0,c4m_loop    ; Repeat for remaining rows
  844. X    movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  845. X    rts                ; Return to caller
  846. X;
  847. X;    Handle inner longword count of zero
  848. X;
  849. XCopy4Quick:
  850. X    Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 1
  851. X    Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 2
  852. X    Advance        a0,a1        ; Increment bitplane 1 ptrs
  853. X    Advance        a2,a3        ; Increment bitplane 2 ptrs
  854. X    movem.l        a0-a3,-(sp)    ; Save bitplane 1,2 ptrs
  855. X    movem.l        (a6),a0-a3    ; Load bitplane 3,4 ptrs
  856. X    Copy_Quick    a0,a1        ; Copy left/right edge of bitplane 3
  857. X    Copy_Quick    a2,a3        ; Copy left/right edge of bitplane 4
  858. X    Advance        a0,a1        ; Increment bitplane 3 ptrs
  859. X    Advance        a2,a3        ; Increment bitplane 4 ptrs
  860. X    movem.l        a0-a3,(a6)    ; Save bitplane 3,4 ptrs
  861. X    movem.l        (sp)+,a0-a3    ; Restore bitplane 1,2 ptrs
  862. X    dbra        d0,Copy4Quick    ; Repeat for all rows
  863. X    movem.l    (sp)+,a0-a3/a6/d0-d7    ; Restore registers
  864. X    rts                ; Return to caller
  865. X
  866. X*****************************************************************************
  867. X*
  868. X*    CopySingle()
  869. X*
  870. X*    The following routines copy from 1 to 4 bitplanes that start and end
  871. X*    (horizontally) within a single longword. CopyMultiple can't be used
  872. X*    for such cases, since it always copies at least two longwords (one
  873. X*    for the left edge and one for the right).
  874. X*
  875. X*    Input:
  876. X*        D0 - Number of rows to copy
  877. X*        D1 - Mask of bits to be copied from source  (000xxx000)
  878. X*        A4 - Modulo of source bitplane
  879. X*        A5 - Modulo of dest bitplane
  880. X*
  881. X*    In addition, pointers to the source/destination bitplanes are pushed
  882. X*    onto the stack, such that 4(SP) = src bp1, 8(SP) = dest bp1,
  883. X*    12(SP) = src bp2, 16(SP) = dest bp2 etc.
  884. X*
  885. X*    Output:
  886. X*        None
  887. X*
  888. X*****************************************************************************
  889. X
  890. X*****************************************************************************
  891. X*
  892. X*    Macros used by the copy routines
  893. X*
  894. X*****************************************************************************
  895. X
  896. X;-----------------------------------------------------------------------------
  897. X;    Init_Sing
  898. X;
  899. X;    This macro is the standard entry to each CopySingle() routine. It
  900. X;    creates the complement mask used for masking source/destination
  901. X;    and adjusts the row counter to be zero based.
  902. X;-----------------------------------------------------------------------------
  903. X
  904. XInit_Sing macro
  905. X    subq.l    #1,d0            ; Adjust row count to zero-based
  906. X    move.l    d1,d2            ; Copy mask
  907. X    not.l    d2            ; And make mask for dest bitplane
  908. X    endm
  909. X
  910. X;-----------------------------------------------------------------------------
  911. X;    Copy_Dual src,dest
  912. X;
  913. X;    Copies the source longword from src to dest, masked with the value
  914. X;    in D2/D4
  915. X;-----------------------------------------------------------------------------
  916. X
  917. XCopy_Dual macro
  918. X    move.l    (\1)+,d3        ; Read src word
  919. X    and.l    d1,d3            ; Mask out unwanted bits
  920. X    move.l    (\2),d4            ; Read dest word
  921. X    and.l    d2,d4            ; Mask out bits to be replaced
  922. X    or.l    d3,d4            ; Combine src and dest bits
  923. X    move.l    d4,(\2)+        ; Replace destination word
  924. X    endm
  925. X
  926. X*****************************************************************************
  927. X*
  928. X*    The actual copy routines, Copy1Single() ... Copy4Single()
  929. X*
  930. X*****************************************************************************
  931. X
  932. X;-----------------------------------------------------------------------------
  933. X;
  934. X;    Copies a single bitplane one longword wide
  935. X;
  936. X;-----------------------------------------------------------------------------
  937. X
  938. XCopy1Single:
  939. X    movem.l    a0-a1/a6/d0-d4,-(sp)    ; Save registers
  940. X    lea        36(sp),a6    ; Get pointer to bitplane
  941. X    move.l        (a6)+,a0    ; Get bitplane pointers into registers
  942. X    move.l        (a6),a1        ;
  943. X    Init_Sing            ; Initialise masks etc.
  944. Xcopy1slp:
  945. X    Copy_Dual    a0,a1        ; Copy longword
  946. X    Advance        a0,a1        ; Move to next longword
  947. X    dbra        d0,copy1slp    ; Repeat for all rows
  948. X    movem.l    (sp)+,a0-a1/a6/d0-d4    ; Restore registers
  949. X    rts
  950. X
  951. X;-----------------------------------------------------------------------------
  952. X;
  953. X;    Copies two bitplanes, each one longword wide
  954. X;
  955. X;-----------------------------------------------------------------------------
  956. X
  957. XCopy2Single:
  958. X    movem.l    a0-a3/a6/d0-d4,-(sp)    ; Save registers
  959. X    lea        44(sp),a6    ; Get ptr to bitplane
  960. X    movem.l        (a6)+,a0-a3    ; Get bitplane ptrs into registers
  961. X    Init_Sing            ; Initialise masks etc.
  962. Xcopy2slp:
  963. X    Copy_Dual    a0,a1        ; Copy longword for bitplane 1
  964. X    Copy_Dual    a2,a3        ; Copy longword for bitplane 2
  965. X    Advance        a0,a1        ; Advance bitplane 1 ptrs
  966. X    Advance        a2,a3        ; Advance bitplane 2 ptrs
  967. X    dbra        d0,copy2slp    ; Repeat for all rows
  968. X    movem.l    (sp)+,a0-a3/a6/d0-d4    ; Restore registers
  969. X    rts
  970. X
  971. X;-----------------------------------------------------------------------------
  972. X;
  973. X;    Copies three bitplanes, each one longword wide
  974. X;
  975. X;-----------------------------------------------------------------------------
  976. X
  977. XCopy3Single:
  978. X    movem.l    a0-a3/a6/d0-d4,-(sp)    ; Save registers
  979. X    lea        44(sp),a6    ; Get pointer to bitplane
  980. X    movem.l        (a6)+,a0-a3    ; Get bitplane ptrs into registers
  981. X    Init_Sing            ; Initialise masks etc.
  982. Xcopy3slp:
  983. X    Copy_Dual    a0,a1        ; Copy longword for bitplane 1
  984. X    Copy_Dual    a2,a3        ; Copy longword for bitplane 2
  985. X    Advance        a0,a1        ; Advance bitplane 1 ptrs
  986. X    Advance        a2,a3        ; Advance bitplane 2 ptrs
  987. X    move.l        a1,-(sp)    ; Save bitplane 2 ptrs
  988. X    move.l        a0,-(sp)    ;
  989. X    move.l        (a6)+,a0    ; Load bitplane 3 ptrs
  990. X    move.l        (a6),a1        ; 
  991. X    Copy_Dual    a0,a1        ; Copy longword for bitplane 3
  992. X    Advance        a0,a1        ; Advance bitplane 3 ptrs
  993. X    move.l        a1,(a6)        ; Save bitplane 3 ptrs
  994. X    move.l        a0,-(a6)    ;
  995. X    move.l        (sp)+,a0    ; Restore bitplane 2 ptrs
  996. X    move.l        (sp)+,a1    ;
  997. X    dbra        d0,copy3slp    ; Repeat for all rows
  998. X    movem.l    (sp)+,a0-a3/a6/d0-d4    ; Restore registers
  999. X    rts
  1000. X
  1001. X;-----------------------------------------------------------------------------
  1002. X;
  1003. X;    Copies four bitplanes, each one longword wide
  1004. X;
  1005. X;-----------------------------------------------------------------------------
  1006. X
  1007. XCopy4Single:
  1008. X    movem.l    a0-a3/a6/d0-d4,-(sp)    ; Save registers
  1009. X    lea        44(sp),a6    ; Get pointer to bitplane pointers
  1010. X    movem.l        (a6)+,a0-a3    ; Get bitplane pointers into registers
  1011. X    Init_Sing            ; Initialise masks etc.
  1012. Xcopy4slp:
  1013. X    Copy_Dual    a0,a1        ; Copy longword for bitplane 1
  1014. X    Copy_Dual    a2,a3        ; Copy longword for bitplane 2
  1015. X    Advance        a0,a1        ; Advance bitplane 1 ptrs
  1016. X    Advance        a2,a3        ; Advance bitplane 2 ptrs
  1017. X    movem.l        a0-a3,-(sp)    ; Save bitplane 1 and 2 ptrs on stack
  1018. X    movem.l        (a6),a0-a3    ; Read bitplane 3 and 4 ptrs
  1019. X    Copy_Dual    a0,a1        ; Copy longword for bitplane 3
  1020. X    Copy_Dual    a2,a3        ; Copy longword for bitplane 4
  1021. X    Advance        a0,a1        ; Advance bitplane 3 ptrs
  1022. X    Advance        a2,a3        ; Advance bitplane 4 ptrs
  1023. X    movem.l        a0-a3,(a6)    ; Save bitplane 3 and 4 ptrs
  1024. X    movem.l        (sp)+,a0-a3    ; Restore bitplane 1 and 2 ptrs
  1025. X    dbra        d0,copy4slp    ; Repeat for all rows
  1026. X    movem.l    (sp)+,a0-a3/a6/d0-d4    ; Restore registers
  1027. X    rts
  1028. X
  1029. X*****************************************************************************
  1030. X*
  1031. X*    Fill_1s(), Fill_0s
  1032. X*
  1033. X*    Handles the case new for Workbench 2.0 where the source bitplane
  1034. X*    pointer points to an array of all ones (ptr = $FFFFFFFF) or all
  1035. X*    zeros ($ptr = $00000000).
  1036. X*
  1037. X*        Input:
  1038. X*        D0 - Number of rows to copy
  1039. X*        D1 - Mask for left edge of source    (000xxx)
  1040. X*        D2 - Mask for right edge of source    (xxx000)
  1041. X*        D3 - Number of longwords to copy (-1 means single column)
  1042. X*        A1 - Pointer to dest bitplane
  1043. X*        A5 - Modulo of dest bitplane
  1044. X*
  1045. X*        Output:
  1046. X*        None
  1047. X*
  1048. X*****************************************************************************
  1049. X
  1050. XFill_1s:
  1051. X    movem.l    d0/d3/d6-d7/a1,-(sp)    ; Save registers
  1052. X    moveq.l    #-1,d7            ; Set register ready for fills
  1053. X    subq.l    #1,d0            ; Adjust row count to zero-based
  1054. X    move.l    d3,d3            ; Check how many longwords to copy
  1055. X    bmi.s    Fill_1single        ; Branch if only a single longword
  1056. X    subq    #1,d3            ; Adjust longword count to zero based
  1057. X    bmi.s    Fill_1quick        ; If no complete longwords, handle
  1058. X;
  1059. X;    We have more than two longwords to copy, so loop over them all.
  1060. X;
  1061. Xfill_1lp1:
  1062. X    or.l    d1,(a1)+        ; Set bits on left edge of bitplane
  1063. X    move.l    d3,d6            ; Get number of longwords to fill
  1064. Xfill_1lp2:
  1065. X    move.l    d7,(a1)+        ; Fill all the longwords
  1066. X    dbra    d6,fill_1lp2        ;
  1067. X    or.l    d2,(a1)+        ; Set bits on right edge of bitplane
  1068. X    add.l    a5,a1            ; Advance to next bitplane row
  1069. X    dbra    d0,fill_1lp1        ; And repeat until done
  1070. X    movem.l    (sp)+,d0/d3/d6-d7/a1    ; Restore registers
  1071. X    rts                ; Return to caller
  1072. X;
  1073. X;    Only two longwords to copy, the left and right edges
  1074. X;
  1075. XFill_1quick:
  1076. X    or.l    d1,(a1)+        ; Set bits on left edge of bitplane
  1077. X    or.l    d2,(a1)+        ; Set bits on right edge of bitplane
  1078. X    add.l    a5,a1            ; Move to next row
  1079. X    dbra    d0,Fill_1quick        ; Repeat for all rows
  1080. X    movem.l    (sp)+,d0/d3/d6-d7/a1    ; Restore registers
  1081. X    rts                ; Return to caller
  1082. X;
  1083. X;    Only a single longword to copy, with left and right portions masked
  1084. X;
  1085. XFill_1single:
  1086. X    move.l    d1,d6            ; Create new mask
  1087. X    and.l    d2,d6            ; by combining left and right masks
  1088. XFill_1s2:
  1089. X    or.l    d6,(a1)+        ; Fill longword
  1090. X    add.l    a5,a1            ; Advance to next row
  1091. X    dbra    d0,Fill_1s2        ; Repeat for all rows
  1092. X    movem.l    (sp)+,d0/d3/d6-d7/a1    ; Restore registers
  1093. X    rts                ; Return to caller
  1094. X
  1095. X;-----------------------------------------------------------------------------
  1096. X;    Clear bitplane with zeros
  1097. X;-----------------------------------------------------------------------------
  1098. X
  1099. XFill_0s:
  1100. X    movem.l    d0-d3/d6-d7/a1,-(sp)    ; Save registers
  1101. X    not.l    d1            ; Invert masks ready for AND
  1102. X    not.l    d2            ;
  1103. X    moveq.l    #0,d7            ; Clear register ready for fills
  1104. X    subq.l    #1,d0            ; Adjust row count to zero-based
  1105. X    move.l    d3,d3            ; Check how many longwords to copy
  1106. X    bmi.s    Fill_0single        ; Branch if only a single longword
  1107. X    subq    #1,d3            ; Adjust longword count to zero based
  1108. X    bmi.s    Fill_0quick        ; If no complete longwords, handle
  1109. X;
  1110. X;    We have more than two longwords to copy, so loop over them all.
  1111. X;
  1112. Xfill_0lp1:
  1113. X    and.l    d1,(a1)+        ; Set bits on left edge of bitplane
  1114. X    move.l    d3,d6            ; Get number of longwords to fill
  1115. Xfill_0lp2:
  1116. X    move.l    d7,(a1)+        ; Fill all the longwords
  1117. X    dbra    d6,fill_0lp2        ;
  1118. X    and.l    d2,(a1)+        ; Set bits on right edge of bitplane
  1119. X    add.l    a5,a1            ; Advance to next bitplane row
  1120. X    dbra    d0,fill_0lp1        ; And repeat until done
  1121. X    movem.l    (sp)+,d0-d3/d6-d7/a1    ; Restore registers
  1122. X    rts                ; Return to caller
  1123. X;
  1124. X;    Only two longwords to copy, the left and right edges
  1125. X;
  1126. XFill_0quick:
  1127. X    and.l    d1,(a1)+        ; Clear left edge of bitplane
  1128. X    and.l    d2,(a1)+        ; Clear right edge of bitplane
  1129. X    add.l    a5,a1            ; Move to next row
  1130. X    dbra    d0,Fill_0quick        ; Repeat for all rows
  1131. X    movem.l    (sp)+,d0-d3/d6-d7/a1    ; Restore registers
  1132. X    rts                ; Return to caller
  1133. X;
  1134. X;    Only a single longword to copy, with left and right portions masked
  1135. X;
  1136. XFill_0single:
  1137. X    move.l    d1,d6            ; Combine left and right edges
  1138. X    or.l    d2,d6            ; to create new mask
  1139. XFill_0s2:
  1140. X    and.l    d6,(a1)+        ; Fill longword
  1141. X    add.l    a5,a1            ; Advance to next row
  1142. X    dbra    d0,Fill_0s2        ; Repeat for all rows
  1143. X    movem.l    (sp)+,d0-d3/d6-d7/a1    ; Restore registers
  1144. X    rts                ; Return to caller
  1145. X
  1146. X*****************************************************************************
  1147. X*
  1148. X*    These two tables give the mask values used when copying the
  1149. X*    bits at the edge of each bitplane row. Note that a right edge
  1150. X*    of zero bits in width is handled as a special case in the code
  1151. X*    (it gets converted to a bitmap which is one longword narrower
  1152. X*    but has a right edge 32 bits wide).
  1153. X*
  1154. X*****************************************************************************
  1155. X
  1156. XLeftMask:
  1157. X    dc.l    $ffffffff,$7fffffff,$3fffffff,$1fffffff
  1158. X    dc.l    $0fffffff,$07ffffff,$03ffffff,$01ffffff
  1159. X    dc.l    $00ffffff,$007fffff,$003fffff,$001fffff
  1160. X    dc.l    $000fffff,$0007ffff,$0003ffff,$0001ffff
  1161. X    dc.l    $0000ffff,$00007fff,$00003fff,$00001fff
  1162. X    dc.l    $00000fff,$000007ff,$000003ff,$000001ff
  1163. X    dc.l    $000000ff,$0000007f,$0000003f,$0000001f
  1164. X    dc.l    $0000000f,$00000007,$00000003,$00000001
  1165. X
  1166. XRightMask:
  1167. X    dc.l    $ffffffff,$80000000,$c0000000,$e0000000
  1168. X    dc.l    $f0000000,$f8000000,$fc000000,$fe000000
  1169. X    dc.l    $ff000000,$ff800000,$ffc00000,$ffe00000
  1170. X    dc.l    $fff00000,$fff80000,$fffc0000,$fffe0000
  1171. X    dc.l    $ffff0000,$ffff8000,$ffffc000,$ffffe000
  1172. X    dc.l    $fffff000,$fffff800,$fffffc00,$fffffe00
  1173. X    dc.l    $ffffff00,$ffffff80,$ffffffc0,$ffffffe0
  1174. X    dc.l    $fffffff0,$fffffff8,$fffffffc,$fffffffe
  1175. X
  1176. X
  1177. X*****************************************************************************
  1178. X*
  1179. X*    Variables used by the code. _UsageCount is only ever updated
  1180. X*    atomically (since the replacement code must be re-entrant), and
  1181. X*    _BlitFunc is initialised by the startup code.
  1182. X*
  1183. X*****************************************************************************
  1184. X
  1185. X    SECTION Scroll,DATA
  1186. X
  1187. X    cnop    0,4
  1188. X
  1189. X_UsageCount:    dc.l    -1        ; Number of callers currently in code
  1190. X_BlitFunc:    dc.l    _StartBlit    ; Address of function for blitter test
  1191. X_OnlySingle:    dc.l    0        ; Only use CPU when src bm == dest bm?
  1192. X_Broken:    dc.l    0        ; Accomodate broken software?
  1193. X_MinTaskPri:    dc.b    0        ; Ignore tasks with pri <= this
  1194. XPad        dc.b    0,0,0        ; Padding to round to LW boundary
  1195. X
  1196. X    END
  1197. X
  1198. END_OF_FILE
  1199. if test 42602 -ne `wc -c <'src/scroll.s'`; then
  1200.     echo shar: \"'src/scroll.s'\" unpacked with wrong size!
  1201. fi
  1202. # end of 'src/scroll.s'
  1203. fi
  1204. echo shar: End of archive 2 \(of 2\).
  1205. cp /dev/null ark2isdone
  1206. MISSING=""
  1207. for I in 1 2 ; do
  1208.     if test ! -f ark${I}isdone ; then
  1209.     MISSING="${MISSING} ${I}"
  1210.     fi
  1211. done
  1212. if test "${MISSING}" = "" ; then
  1213.     echo You have unpacked both archives.
  1214.     rm -f ark[1-9]isdone
  1215. else
  1216.     echo You still need to unpack the following archives:
  1217.     echo "        " ${MISSING}
  1218. fi
  1219. ##  End of shell archive.
  1220. exit 0
  1221. -- 
  1222. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  1223. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  1224. Post requests for sources, and general discussion to comp.sys.amiga.misc.
  1225.